import * as fs from 'fs';
import * as path from 'path';

export interface PackageMoveResult {
  success: boolean;
  message: string;
  newFilePath?: string;
  updatedReferences: Array<{
    filePath: string;
    oldImport: string;
    newImport: string;
  }>;
  moveDetails?: string[];
  errors?: string[];
}

export interface ImportReference {
  filePath: string;
  lineNumber: number;
  originalImport: string;
  className: string;
}

/**
 * 包移动器 - 将文件从一个包移动到另一个包，并自动更新所有引用的import语句
 */
export class PackageMover {

  async moveToPackage(
    sourceFilePath: string, 
    targetPackage: string, 
    projectPath: string, 
    updateReferences: boolean = true
  ): Promise<PackageMoveResult> {
    const result: PackageMoveResult = {
      success: false,
      message: '',
      updatedReferences: [],
      moveDetails: [],
      errors: []
    };

    try {
      console.error(`[PackageMover] 开始移动包`);
      console.error(`[PackageMover] 源文件: ${sourceFilePath}`);
      console.error(`[PackageMover] 目标包: ${targetPackage}`);
      console.error(`[PackageMover] 项目路径: ${projectPath}`);
      
      if (!fs.existsSync(sourceFilePath)) {
        result.errors?.push('源文件不存在');
        result.message = '源文件不存在';
        return result;
      }

      const sourceContent = fs.readFileSync(sourceFilePath, 'utf-8');
      const className = this.extractClassName(sourceContent);
      
      if (!className) {
        result.errors?.push('无法识别源文件的类名');
        result.message = '无法识别源文件的类名';
        return result;
      }

      const originalPackage = this.extractPackageName(sourceContent);
      console.error(`[PackageMover] 原包名: ${originalPackage}`);
      console.error(`[PackageMover] 类名: ${className}`);

      // 如果包名相同，无需移动
      if (originalPackage === targetPackage) {
        result.success = true;
        result.message = '目标包与当前包相同，无需移动';
        return result;
      }

      // 计算目标文件路径
      const targetDir = this.packageToPath(targetPackage, projectPath);
      const targetFilePath = path.join(targetDir, path.basename(sourceFilePath));

      console.error(`[PackageMover] 目标目录: ${targetDir}`);
      console.error(`[PackageMover] 目标文件路径: ${targetFilePath}`);

      // 创建目标目录
      if (!fs.existsSync(targetDir)) {
        fs.mkdirSync(targetDir, { recursive: true });
        result.moveDetails?.push(`创建目标目录: ${targetDir}`);
      }

      // 检查目标文件是否已存在
      if (fs.existsSync(targetFilePath)) {
        result.errors?.push(`目标文件已存在: ${targetFilePath}`);
        result.message = '目标文件已存在';
        return result;
      }

      // 更新文件内容的package语句
      const updatedContent = this.updatePackageStatement(sourceContent, targetPackage);

      // 查找所有引用该类的文件
      let references: ImportReference[] = [];
      if (updateReferences) {
        references = await this.findImportReferences(projectPath, originalPackage, className, sourceFilePath);
        console.error(`[PackageMover] 找到 ${references.length} 个import引用`);
      }

      // 写入目标文件
      fs.writeFileSync(targetFilePath, updatedContent, 'utf-8');
      result.newFilePath = targetFilePath;
      result.moveDetails?.push(`文件移动至: ${targetFilePath}`);

      // 删除源文件
      fs.unlinkSync(sourceFilePath);
      result.moveDetails?.push(`删除源文件: ${sourceFilePath}`);

      // 更新所有引用该类的import语句
      if (updateReferences && references.length > 0) {
        for (const ref of references) {
          try {
            const updateCount = await this.updateImportStatement(
              ref.filePath, 
              originalPackage, 
              targetPackage, 
              className
            );
            
            if (updateCount > 0) {
              result.updatedReferences.push({
                filePath: ref.filePath,
                oldImport: `import ${originalPackage}.${className};`,
                newImport: `import ${targetPackage}.${className};`
              });
              console.error(`[PackageMover] 更新import: ${ref.filePath}`);
            }
          } catch (error) {
            result.errors?.push(`更新引用文件失败 ${ref.filePath}: ${error}`);
          }
        }
      }

      result.success = true;
      result.message = `成功将 ${className} 从 ${originalPackage} 移动到 ${targetPackage}`;

    } catch (error) {
      result.errors?.push(`包移动失败: ${error}`);
      result.message = `包移动失败: ${error}`;
      console.error(`[PackageMover] 错误:`, error);
    }

    return result;
  }

  private extractClassName(content: string): string | null {
    const match = content.match(/(?:public\s+)?(?:class|interface|enum)\s+(\w+)/);
    return match ? match[1] : null;
  }

  private extractPackageName(content: string): string {
    const match = content.match(/package\s+([^;]+);/);
    return match ? match[1].trim() : '';
  }

  private packageToPath(packageName: string, projectPath: string): string {
    // 将包名转换为文件路径
    const packagePath = packageName.replace(/\./g, path.sep);
    
    // 尝试找到合适的源代码目录
    const commonSrcPaths = [
      'src/main/java',
      'src',
      ''  // 直接使用项目根目录
    ];
    
    for (const srcPath of commonSrcPaths) {
      const fullSrcPath = path.join(projectPath, srcPath);
      if (fs.existsSync(fullSrcPath)) {
        return path.join(fullSrcPath, packagePath);
      }
    }
    
    // 如果都不存在，使用项目根目录
    return path.join(projectPath, packagePath);
  }

  private updatePackageStatement(content: string, newPackage: string): string {
    // 更新package语句
    return content.replace(/package\s+[^;]+;/, `package ${newPackage};`);
  }

  private async findImportReferences(
    projectPath: string, 
    originalPackage: string, 
    className: string, 
    excludeFilePath: string
  ): Promise<ImportReference[]> {
    const references: ImportReference[] = [];
    
    const searchDir = async (dirPath: string) => {
      if (!fs.existsSync(dirPath)) return;
      
      const entries = fs.readdirSync(dirPath, { withFileTypes: true });
      
      for (const entry of entries) {
        const fullPath = path.join(dirPath, entry.name);
        
        if (entry.isDirectory()) {
          if (!this.shouldSkipDirectory(entry.name)) {
            await searchDir(fullPath);
          }
        } else if (entry.isFile() && entry.name.endsWith('.java') && fullPath !== excludeFilePath) {
          const fileReferences = await this.findImportReferencesInFile(fullPath, originalPackage, className);
          references.push(...fileReferences);
        }
      }
    };
    
    await searchDir(projectPath);
    return references;
  }

  private shouldSkipDirectory(dirName: string): boolean {
    const skipDirs = [
      'node_modules', '.git', '.idea', '.vscode', 'target', 'build', 
      'dist', 'out', '.gradle', 'bin', 'logs', 'temp', 'tmp'
    ];
    return skipDirs.includes(dirName) || dirName.startsWith('.');
  }

  private async findImportReferencesInFile(
    filePath: string, 
    originalPackage: string, 
    className: string
  ): Promise<ImportReference[]> {
    const references: ImportReference[] = [];
    
    try {
      const content = fs.readFileSync(filePath, 'utf-8');
      const lines = content.split('\n');
      
      for (let i = 0; i < lines.length; i++) {
        const line = lines[i].trim();
        
        // 检查import语句
        if (line.startsWith('import ') && line.includes(`${originalPackage}.${className}`)) {
          references.push({
            filePath,
            lineNumber: i + 1,
            originalImport: line,
            className
          });
        }
        
        // 检查import static语句
        if (line.startsWith('import static ') && line.includes(`${originalPackage}.${className}`)) {
          references.push({
            filePath,
            lineNumber: i + 1,
            originalImport: line,
            className
          });
        }
        
        // 检查通配符import（如果有的话）
        if (line.startsWith('import ') && line.includes(`${originalPackage}.*`)) {
          // 需要检查文件中是否实际使用了该类
          if (this.classIsUsedInFile(content, className)) {
            references.push({
              filePath,
              lineNumber: i + 1,
              originalImport: line,
              className
            });
          }
        }
      }
    } catch (error) {
      console.error(`[PackageMover] 读取文件失败: ${filePath}`, error);
    }
    
    return references;
  }

  private classIsUsedInFile(content: string, className: string): boolean {
    // 简单检查类名是否在文件中被使用
    const patterns = [
      new RegExp(`\\b${className}\\b`), // 类名被直接使用
      new RegExp(`new\\s+${className}\\s*\\(`), // 构造函数调用
      new RegExp(`${className}\\.\\w+`), // 静态方法/字段调用
      new RegExp(`\\(\\s*${className}\\s+\\w+\\s*\\)`), // 方法参数类型
      new RegExp(`<\\s*${className}\\s*>`), // 泛型类型
      new RegExp(`extends\\s+${className}`), // 继承
      new RegExp(`implements\\s+.*${className}`) // 实现接口
    ];
    
    return patterns.some(pattern => pattern.test(content));
  }

  private async updateImportStatement(
    filePath: string, 
    oldPackage: string, 
    newPackage: string, 
    className: string
  ): Promise<number> {
    let changeCount = 0;
    
    try {
      let content = fs.readFileSync(filePath, 'utf-8');
      const originalContent = content;
      
      // 更新普通import语句
      const importPattern = new RegExp(
        `import\\s+${oldPackage.replace(/\./g, '\\.')}\\.${className}\\s*;`,
        'g'
      );
      
      content = content.replace(importPattern, (match) => {
        changeCount++;
        return `import ${newPackage}.${className};`;
      });
      
      // 更新import static语句
      const importStaticPattern = new RegExp(
        `import\\s+static\\s+${oldPackage.replace(/\./g, '\\.')}\\.${className}\\.(\\w+)\\s*;`,
        'g'
      );
      
      content = content.replace(importStaticPattern, (match, memberName) => {
        changeCount++;
        return `import static ${newPackage}.${className}.${memberName};`;
      });
      
      // 更新通配符import（如果文件中使用了该类）
      if (this.classIsUsedInFile(content, className)) {
        const wildcardPattern = new RegExp(
          `import\\s+${oldPackage.replace(/\./g, '\\.')}\\s*\\.\\s*\\*\\s*;`,
          'g'
        );
        
        // 如果使用了通配符import，需要添加具体的import
        if (wildcardPattern.test(content)) {
          const wildcardImportLine = content.match(wildcardPattern)?.[0];
          if (wildcardImportLine) {
            // 在通配符import后添加新的具体import
            const insertPosition = content.indexOf(wildcardImportLine) + wildcardImportLine.length;
            const newImport = `\nimport ${newPackage}.${className};`;
            content = content.slice(0, insertPosition) + newImport + content.slice(insertPosition);
            changeCount++;
          }
        }
      }
      
      // 如果有变更，写回文件
      if (content !== originalContent) {
        fs.writeFileSync(filePath, content, 'utf-8');
        console.error(`[PackageMover] 更新import语句: ${filePath}`);
      }
      
    } catch (error) {
      console.error(`[PackageMover] 更新import语句失败: ${filePath}`, error);
    }
    
    return changeCount;
  }

  /**
   * 移动整个包目录
   */
  async movePackageDirectory(
    sourcePackage: string,
    targetPackage: string,
    projectPath: string
  ): Promise<PackageMoveResult> {
    const result: PackageMoveResult = {
      success: false,
      message: '',
      updatedReferences: [],
      moveDetails: [],
      errors: []
    };

    try {
      const sourceDir = this.packageToPath(sourcePackage, projectPath);
      const targetDir = this.packageToPath(targetPackage, projectPath);

      if (!fs.existsSync(sourceDir)) {
        result.errors?.push('源包目录不存在');
        result.message = '源包目录不存在';
        return result;
      }

      if (fs.existsSync(targetDir)) {
        result.errors?.push('目标包目录已存在');
        result.message = '目标包目录已存在';
        return result;
      }

      // 获取源目录中的所有Java文件
      const javaFiles = this.getJavaFilesInDirectory(sourceDir);
      console.error(`[PackageMover] 找到 ${javaFiles.length} 个Java文件需要移动`);

      // 创建目标目录
      fs.mkdirSync(targetDir, { recursive: true });

      // 移动每个Java文件
      for (const javaFile of javaFiles) {
        const relativePath = path.relative(sourceDir, javaFile);
        const targetFilePath = path.join(targetDir, relativePath);
        
        // 确保目标子目录存在
        const targetFileDir = path.dirname(targetFilePath);
        if (!fs.existsSync(targetFileDir)) {
          fs.mkdirSync(targetFileDir, { recursive: true });
        }

        // 更新文件内容的package语句
        const content = fs.readFileSync(javaFile, 'utf-8');
        const className = this.extractClassName(content);
        const updatedContent = this.updatePackageStatement(content, targetPackage);

        // 写入目标文件
        fs.writeFileSync(targetFilePath, updatedContent, 'utf-8');
        result.moveDetails?.push(`移动文件: ${relativePath}`);

        // 查找并更新引用
        if (className) {
          const references = await this.findImportReferences(projectPath, sourcePackage, className, javaFile);
          
          for (const ref of references) {
            const updateCount = await this.updateImportStatement(ref.filePath, sourcePackage, targetPackage, className);
            if (updateCount > 0) {
              result.updatedReferences.push({
                filePath: ref.filePath,
                oldImport: `import ${sourcePackage}.${className};`,
                newImport: `import ${targetPackage}.${className};`
              });
            }
          }
        }

        // 删除源文件
        fs.unlinkSync(javaFile);
      }

      // 删除空的源目录
      this.removeEmptyDirectories(sourceDir, projectPath);

      result.success = true;
      result.message = `成功将包 ${sourcePackage} 移动到 ${targetPackage}`;

    } catch (error) {
      result.errors?.push(`包目录移动失败: ${error}`);
      result.message = `包目录移动失败: ${error}`;
      console.error(`[PackageMover] 错误:`, error);
    }

    return result;
  }

  private getJavaFilesInDirectory(dirPath: string): string[] {
    const javaFiles: string[] = [];
    
    const scanDirectory = (currentDir: string) => {
      if (!fs.existsSync(currentDir)) return;
      
      const entries = fs.readdirSync(currentDir, { withFileTypes: true });
      
      for (const entry of entries) {
        const fullPath = path.join(currentDir, entry.name);
        
        if (entry.isDirectory()) {
          scanDirectory(fullPath);
        } else if (entry.isFile() && entry.name.endsWith('.java')) {
          javaFiles.push(fullPath);
        }
      }
    };
    
    scanDirectory(dirPath);
    return javaFiles;
  }

  private removeEmptyDirectories(dirPath: string, projectPath: string) {
    try {
      // 只在项目目录内操作，避免删除项目外的目录
      if (!dirPath.startsWith(projectPath)) {
        return;
      }

      const entries = fs.readdirSync(dirPath);
      
      // 如果目录为空，删除它
      if (entries.length === 0) {
        fs.rmdirSync(dirPath);
        console.error(`[PackageMover] 删除空目录: ${dirPath}`);
        
        // 递归删除父目录（如果也为空）
        const parentDir = path.dirname(dirPath);
        if (parentDir !== projectPath && parentDir !== dirPath) {
          this.removeEmptyDirectories(parentDir, projectPath);
        }
      }
    } catch (error) {
      console.error(`[PackageMover] 删除目录失败: ${dirPath}`, error);
    }
  }
}